﻿using CQRSFramework.Commands;
using CQRSFramework.Commands.Impl;
using CQRSFramework.Common.Components;
using CQRSFramework.Common.Configurations;
using CQRSFramework.Domains;
using CQRSFramework.Domains.Impl;
using CQRSFramework.Events;
using CQRSFramework.Events.Impl;
using CQRSFramework.Infrustructures;
using CQRSFramework.Infrustructures.Impl;
using System;
using System.Linq;
using System.Reflection;

namespace CQRSFramework.Extensions
{
    public static class ConfigurationExtensions
    {
        public static CommonConfiguration RegisterCQRSFrameworkAssemblies(this CommonConfiguration configuration, Assembly[] assemblies)
        {
            ObjectContainer.RegisterInstance<ICommandHandlerProvider, CommandHandlerProvider>(new CommandHandlerProvider(assemblies));
            ObjectContainer.RegisterInstance<ITypeNameProvider, TypeNameProvider>(new TypeNameProvider(assemblies));
            ObjectContainer.RegisterInstance<IAggregateRootInternalEventHandlerProvider, AggregateRootInternalEventHandlerProvider>(new AggregateRootInternalEventHandlerProvider(assemblies));
            ObjectContainer.RegisterGeneric(typeof(IRoutingKeyProvider<>), typeof(RoutingKeyProvider<>));
            foreach (var assembly in assemblies)
            {
                foreach (var handlerType in assembly.GetTypes().Where(t => IsCQRSFrameworkComponents(t)))
                {
                    var handlerInterfaces = handlerType.GetInterfaces().Where(a => a.IsGenericType);
                    foreach (var handlerInterface in handlerInterfaces)
                    {
                        ObjectContainer.RegisterType(handlerInterface, handlerType);
                    }
                }
            }
            return configuration;
        }
        private static bool IsCQRSFrameworkComponents(Type type)
        {
            return type.IsClass && type.GetInterfaces().Any(a => a.IsGenericType
            && (a.GetGenericTypeDefinition() == typeof(ICommandHandler<>)
            || a.GetGenericTypeDefinition() == typeof(IEventHandler<>)
            ));
        }
        public static CommonConfiguration RegisterCommonComponents(this CommonConfiguration configuration)
        {
            ObjectContainer.Register<ICommandContext, CommandContext>();
            ObjectContainer.Register<IEventJsonSerializer, EventJsonSerializer>();
            ObjectContainer.Register<IAggregateFactory, AggregateFactory>();
            ObjectContainer.Register<IEventBus, EventBus>();
            ObjectContainer.Register<IEventService, EventService>();
            ObjectContainer.Register<ICommandProcess, DefaultCommandProcess>();
            ObjectContainer.Register<IEventProcess, DefaultEventProcess>();
            ObjectContainer.Register<IProcessingCommandHandler, ProcessingCommandHandler>();
            ObjectContainer.Register<IProcessingEventHandler, ProcessingEventHandler>();
            return configuration;
        }
    }
}
